package com.yuezhix.elastic;

import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;


@SpringBootApplication
@RestController
public class ElasticApplication {

    @Autowired
    private TransportClient client;


//    查询
    @GetMapping("/get/book/novel")
    @ResponseBody
    public ResponseEntity get(@RequestParam(name = "id", defaultValue = "") String id) {


        if (id.isEmpty()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }

        GetResponse getFields = this.client.prepareGet("book", "novel", id).get();

        if (getFields.isExists()) {
            return new ResponseEntity(getFields.getSource(), HttpStatus.OK);
        }

        return new ResponseEntity(HttpStatus.NOT_FOUND);
    }


//    添加
    @PostMapping("add/book/novel")
    @ResponseBody
    public ResponseEntity add(
            @RequestParam(name = "title", defaultValue = "") String title,
            @RequestParam(name = "author", defaultValue = "") String author,
            @RequestParam(name = "word_count", defaultValue = "") String word_count,
            @RequestParam(name = "date", defaultValue = "") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date

    ) {
        try {
//            重构保存的参数格式
            XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
                    .startObject()
                    .field("title", title)
                    .field("author", author)
                    .field("word_count", word_count)
                    .field("date", date.getTime())
                    .endObject();
//            构建索引
            IndexResponse response = this.client.prepareIndex("book", "novel")
                    .setSource(xContentBuilder)
                    .get();
            return new ResponseEntity(response.getId(), HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

//    删除
    @DeleteMapping("del/book/novel")
    @ResponseBody
    public ResponseEntity del(@RequestParam(name = "id", defaultValue = "") String id) {
        if (id.isEmpty()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }

        DeleteResponse response = this.client.prepareDelete("book", "novel", id).get();

        return new ResponseEntity(response.getResult().toString(), HttpStatus.OK);

    }

//    更新
    @PutMapping("update/book/novel")
    @ResponseBody
    public ResponseEntity update(
            @RequestParam(name = "id", defaultValue = "") String id,
            @RequestParam(name = "title", required = false) String title,
            @RequestParam(name = "author", required = false) String author
    ) {

//        找到要修改的文档  (索引, 类型, 唯一标识)
        UpdateRequest updateRequest = new UpdateRequest("book", "novel", id);

        try {
            XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
                    .startObject();

            if (title != null) {
                xContentBuilder.field("title", title);
            }

            if (author != null) {
                xContentBuilder.field("author", author);
            }

            xContentBuilder.endObject();

            updateRequest.doc(xContentBuilder);

        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        try {
            UpdateResponse response = this.client.update(updateRequest).get();
            return new ResponseEntity(response.getResult(),HttpStatus.OK);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }



//    复合查询
    @PostMapping("query/book/novel")
    @ResponseBody
    public ResponseEntity query(
            @RequestParam(name = "author" ,required = false) String author,
            @RequestParam(name = "title" ,required = false) String title,
            @RequestParam(name = "gt_word_count" ,defaultValue = "0") int gtWordCount,
            @RequestParam(name = "lt_word_count" ,required = false) Integer ltWordCount
    ){

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        if (author != null){
            boolQuery.must(QueryBuilders.matchQuery("author",author));
        }

        if (title != null){
            boolQuery.must(QueryBuilders.matchQuery("title",title));
        }

        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("word_count")
                .from(gtWordCount);

        if (ltWordCount != null  && ltWordCount >= gtWordCount){
            rangeQuery.to(ltWordCount);
        }

        boolQuery.filter(rangeQuery);

        SearchRequestBuilder builder = this.client.prepareSearch("book")
                .setTypes("novel")
                .setSearchType(SearchType.QUERY_THEN_FETCH)
                .setQuery(boolQuery)
                .setFrom(0)
                .setSize(10);

        System.out.println(builder);

        SearchResponse response = builder.get();

        System.out.println(response);

        List<Map<String,Object>> result = new ArrayList<>();

        response.getHits().forEach((s)->result.add(s.getSource()));

//        for (SearchHit hit : response.getHits()){
//            result.add(hit.getSource());
//        }

        return new ResponseEntity(result,HttpStatus.OK) ;

    }


    public static void main(String[] args) {
        SpringApplication.run(ElasticApplication.class, args);
    }

}
